package org.moonlight.jvm.rtda.share;

/**
 * 线程共享区: 需要在 JVM 启动时就创建好(当然也可以动态收缩扩展大小)，在 JVM 退出时销毁。
 *
 * 线程共享区是堆和方法区。
 *   堆: 对象数据存放在堆中。因为对象的习性不一样，有的能活很久，一直不死，有的朝生夕死，适用的算法也不一样。所以堆又分为
 *       新生代: 默认1/3堆空间。 -Xmn: 设置新生代大小。空间耗尽时触发YGC/MinorGC
 *              新生代的对象大多都死的快，不用付出太多的复制成本，适用于复制算法，
 *              那就要有个地方给别人复制吧，所以就分为三个区，Eden区作为产房生产对象，两个Survivor区交替使用复制来复制去.
 *
 *              在GC开始的时候，对象只会存在于Eden区和名为From的Survivor区，To区是空的，
 *              一次MinorGc过后，Eden区和SurvivorFrom区存活的对象会移动到SurvivorTo区中，
 *              然后会清空Eden区和SurvivorFrom区，并对存活的对象的年龄+1，如果对象的年龄达到15，则直接分配到老年代。
 *              MinorGC完成后，SurvivorFrom区和SurvivorTo区的功能进行互换。
 *              下一次MinorGC时，会把SurvivorTo区和Eden区存活的对象放入SurvivorFrom区中，并计算对象存活的年龄。
 *
 *       老年代: 老年代，默认2/3堆空间。
 *              老年代存活率比较高，回收比较少，复制成本比较高，适用于标记清除或标记整理
 *              老年代空间耗尽时触发Fullgc/MajorGC，新生代、老年代同时回收
 *
 *
 *   方法区: 类数据存放在方法区中，类数据包括字段和方法信息、方法的字节码、运行时常量池等。
 *          方法区只是一个逻辑概念，而实际需要看具体的虚拟机实现，在 1.8 前方法区是挂在堆上，叫做永久代，1.8之后方法区是直接使用的直接内存，叫做元空间。
 *
 *    JDK1.8及之后字符串常量池和运行时常量池逻辑上属于方法区，但是实际存放在堆内存中，因此既可以说两者存放在堆中，也可以说两则存在于方法区中，这就是造成误解的地方。
 *
 *   为什么在1.8的时候把永久代干掉换成Metaspace？
 *     为了解决永久代的OOM问题，元数据和class对象存放在永久代中，容易出现性能问题和内存溢出,类及方法的信息等比较难确定其大小，因此对于永久代大小指定比较困难，
 *     大小容易出现永久代溢出，太大容易导致老年代溢出, 为GC带来不必要的复杂度，并且回收效率偏低。
 *     元空间则对每个加载器都有专门的存储空间，不会单独回收某个类, 对象的位置都是固定的。
 *
 *     直接内存,受限于系统物理内存  -XX:MetaspaceSize=512M  -XX:MaxMetaspaceSize=1024M
 *
 *
 */